using System.Web;
using System.Xml;
using System;

/*	-----------------------------------------------------------------------	
	Copyright:	umlungu consulting (pty) ltd
	Author:		Alan Benington	
	Started:	2008-03-06	
	Status:		release	
	Version:	2.0.0
	Build:		20080319
	License:	GNU General Public License
	-----------------------------------------------------------------------	*/

/*	-----------------------------------------------------------------------	
	Development Notes:
	==================
	20080306:	Starting point from profileX:
	20080319:	Added configuration support for web service url
	-----------------------------------------------------------------------	*/

namespace umlungu.engineX.blogX {
	/// <summary>
	/// The tokenX class.
	/// <para>Purpose: This class is used to display a html page that is authenticated externally (PassportX).</para>
	/// <para> - It is derived from displayX for basic page display (minus profiled display functionality)</para>
	/// <para> - This class deals with validation and initialisation of user profile from token.</para>
	/// <para></para>
	/// </summary>
	public class tokenX : displayX {
		#region Invisible properties
		#endregion

		#region Config constants
		private const string CONFIG_ELEM = "PassportX";
		private const string customerID = "customer";
		private const string passportID = "passport";
		#endregion

		#region Constants - note that this is a subset of those typically in the iPassport broker (common class calls)
		private const string PROPERTY_VALID = "PXValidate";
		private const string PROPERTY_TOKEN = "PXToken";
		private const string PROPERTY_USERNAME = "Username";
		private const string PROPERTY_PASSWORD = "Password";
		private const string PROPERTY_FIRSTNAME = "FirstName";
		private const string PROPERTY_SURNAME = "Surname";
		private const string PROPERTY_EMAIL = "Email";
		private const string PROPERTY_CELLNO = "Cellphone";
		private const string PROPERTY_USERID = "UserID";
		private const string SELECT_RESULT_CODE = "/Result/ResultCode";
		private const string SELECT_RESULT_DESC = "/Result/Description";
		#endregion

		#region Constants
		private const string SELECT_TOKEN = "@Token";
		private const string SELECT_USERNAME = "/UserName";
		private const string SELECT_PASSWORD = "/Password";
		private const string SELECT_FIRSTNAME = "/FirstName";
		private const string SELECT_SURNAME = "/Surname";
		private const string SELECT_EMAIL = "/EMail";
		private const string SELECT_CELLNO = "/CellPhone";
		private const string SELECT_USERID = "@UserID";
		#endregion

		#region Visible properties
		// see comment against the Constants region - pertains to these properties as well.
		public string Username {
			get { return (UserProfile.Get(PROPERTY_USERNAME) == null) ? "" : UserProfile.Get(PROPERTY_USERNAME).InnerText; }
			set { UserProfile.Add(PROPERTY_USERNAME, value); }
		}
		public string Password {
			get { return (UserProfile.Get(PROPERTY_PASSWORD) == null) ? "" : UserProfile.Get(PROPERTY_PASSWORD).InnerText; }
			set { UserProfile.Add(PROPERTY_PASSWORD, value); }
		}
		public string Firstname {
			get { return (UserProfile.Get(PROPERTY_FIRSTNAME) == null) ? "" : UserProfile.Get(PROPERTY_FIRSTNAME).InnerText; }
			set { UserProfile.Add(PROPERTY_FIRSTNAME, value); }
		}
		public string Surname {
			get { return (UserProfile.Get(PROPERTY_SURNAME) == null) ? "" : UserProfile.Get(PROPERTY_SURNAME).InnerText; }
			set { UserProfile.Add(PROPERTY_SURNAME, value); }
		}
		public string Email {
			get { return (UserProfile.Get(PROPERTY_EMAIL) == null) ? "" : UserProfile.Get(PROPERTY_EMAIL).InnerText; }
			set { UserProfile.Add(PROPERTY_EMAIL, value); }
		}
		public string Cellno {
			get { return (UserProfile.Get(PROPERTY_CELLNO) == null) ? "" : UserProfile.Get(PROPERTY_CELLNO).InnerText; }
			set { UserProfile.Add(PROPERTY_CELLNO, value); }
		}
		public string Token {
			get { return (UserProfile.Get(PROPERTY_TOKEN) == null) ? "" : UserProfile.Get(PROPERTY_TOKEN).InnerText; }
			set { UserProfile.Add(PROPERTY_TOKEN, value); }
		}
		public string UserID {
			get { return (UserProfile.Get(PROPERTY_USERID) == null) ? "" : UserProfile.Get(PROPERTY_USERID).InnerText; }
			set { UserProfile.Add(PROPERTY_USERID, value); }
		}
		public bool FullValidation {
			get { return (UserProfile.Get(PROPERTY_VALID) == null) ? true : (UserProfile.Get(PROPERTY_VALID).InnerText == "full"); }
			set { UserProfile.Add(PROPERTY_VALID, value? "full" : "quick"); }
		}
		#endregion

		#region Constructors/Destructors
		/// <overloads>Constructor</overloads>
		/// <summary>Default constructor</summary>
		public tokenX() : this("tokenX") {
		}
		/// <summary>Constructor for derived classes</summary>
		public tokenX(string label) : base(label) {
		}
		#endregion

		#region Public methods
		#endregion

		#region Protected methods
		/// <summary>Initialises the page, including token validation</summary>
		protected override void _Initialise() {
			base._Initialise();
			checkToken();
		}
		/// <summary>
		/// Post-processes the content for profiling (menus/links at this stage).
		/// NB this is done by calling the base method so that form fields and includes are done first.
		/// </summary>
		protected override void _PostProcessContent() {
			base._PostProcessContent();
			TemplateArguments.AddParam("token", "", Token);
		}

		/// <summary>
		/// Method to do a validation call against the validation web service
		/// </summary>
		/// <returns></returns>
		protected virtual bool _doValidation() {
			return _doValidation(FullValidation);
		}
		/// <summary>
		/// Method to do a validation call against the validation web service
		/// </summary>
		/// <returns></returns>
		protected virtual bool _doValidation(bool isFull) {
			PassportX.WebmailPassportServices passportWS = new umlungu.engineX.blogX.PassportX.WebmailPassportServices();
			passportWS.Url = getUrl(passportID);
			Debugger.Spoor("_doValidation", "passportWS.Url", passportWS.Url);
			XmlElement result = ((isFull) ? passportWS.ValidateUser(Token) : passportWS.Validate(Token)) as XmlElement;
			if (checkWS(result)) {
				if (isFull) {
					Username = getNodeValue(result, SELECT_USERNAME);
					UserID = getNodeValue(result, SELECT_USERID);
					Password = getNodeValue(result, SELECT_PASSWORD);
					Firstname = getNodeValue(result, SELECT_FIRSTNAME);
					Surname = getNodeValue(result, SELECT_SURNAME);
					Email = getNodeValue(result, SELECT_EMAIL);
					Cellno = getNodeValue(result, SELECT_CELLNO);
					FullValidation = false;
				}
				return true;
			} else 
				return false;
		}
		/// <summary>
		/// Method to do (stuff) post the validation call
		/// </summary>
		/// <returns></returns>
		protected virtual void _postValidation() {
		}
		#endregion

		#region Private methods
		private string getUrl(string configID) {
			return Config.Value(String.Concat(CONFIG_ELEM, "/Url[@id='", configID, "']"));
		}
		/// <summary>Retrieve and validate token and re-direct if not valid</summary>
		/// <remarks>Note:
		/// <para>The Token is expected to be passed as a parameter in the url string.</para>
		/// </remarks>
		private void checkToken() {
			string TokenCheck = Parameters.Link.GetAttribute("tokencheck");
			Debugger.Spoor("checkToken", "Token", Token, "TokenCheck", TokenCheck);
			if (TokenCheck != "no") {
				Token = Parameters.Token;
				if (String.IsNullOrEmpty(Parameters.Token) == true) {
					Response.Redirect(Config.InvalidRedirect);
				} else {
					if (_doValidation())
						_postValidation();
					else
						Response.Redirect(Config.InvalidRedirect);
				}
			}
		}

		private string getNodeValue(XmlNode result, string selstr) {
			XmlNode node = result.SelectSingleNode(selstr);
			return (node == null) ? "" : (node.InnerText == "null") ? "" : node.InnerText;
		}

		private bool checkWS(XmlNode result) {
			XmlElement rescode = result.SelectSingleNode(SELECT_RESULT_CODE) as XmlElement;
			if (rescode != null) {
				return (rescode.InnerText == "0");
			} else {
				return false;
			}
		}
		#endregion
	}
}
